package com.jiao.table.listener;

import cn.hutool.core.collection.CollectionUtil;
import com.jiao.comm.exception.ListenerException;
import com.jiao.datasource.parse.SQLCommand;
import com.jiao.table.cache.CacheWrite;
import com.jiao.table.cache.DynamicCacheRead;
import com.jiao.table.cache.DynamicCacheWrite;
import lombok.SneakyThrows;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.sql.SQLException;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @Description
 * @Author Vincent.jiao
 * @Date 2022/5/13 16:58
 */
@Component
public class DeleteSQLListener extends WriteSQLListenerAbstract {
    private Map<SQLCommand, List<Long>> rowIdMap = new ConcurrentHashMap<>();

    @Autowired
    DynamicCacheWrite cacheWrite;

    @Autowired
    DynamicCacheRead cacheRead;

    /**
     * sql 执行前.
     * 执行前获取操作的行id.
     * @param commandInfo
     */
    @Override
    public void execBefore(SQLCommand commandInfo) throws ListenerException  {
        if(!(isDelete(commandInfo))) {
            return;
        }

        if(!isExceCloseLoop(commandInfo)) {
            return;
        }

        try {
            List<Long> ids = getWriteRowId(commandInfo);
            if(CollectionUtil.isNotEmpty(ids)) {
                rowIdMap.put(commandInfo, ids);     //记录受影响行，如果sql执行后，就获取不到了
            }

        } catch (SQLException e) {
            throw new ListenerException(e.getMessage(), e);
        }

        if(commandInfo.getSqlUnit().isAutoCommit()) {
            deleteCache(Arrays.asList(commandInfo));
        }
    }

    /**
     * 提交后.
     * @param sqlCommands
     * @throws ListenerException
     */
    @Override
    public void commiteAfter(List<SQLCommand> sqlCommands) throws ListenerException {
        deleteCache(sqlCommands);
    }

    private void deleteCache(List<SQLCommand> sqlCommands) {
        List<SQLCommand> deleteCommandList = new LinkedList<>();
        for (SQLCommand item : sqlCommands){
            if(!isDelete(item) || !isExceCloseLoop(item)) {
                continue;
            }
            deleteCommandList.add(item);
        }

        if(CollectionUtil.isEmpty(deleteCommandList)) {
            return;
        }

        for (SQLCommand item : deleteCommandList){
            if(CollectionUtil.isNotEmpty(rowIdMap.get(item))) {
                cacheWrite.deleteBatch(item.getTableName().trim(), rowIdMap.get(item));
            }

            rowIdMap.remove(item);
        }
    }
}
